<route lang="json5">
{
  style: {
    navigationBarTitleText: '活动详情',
    navigationStyle: 'custom',
  },
}
</route>

<template>
  <view class="page" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
    <!-- 顶部自定义导航（毛玻璃、下滑显隐） -->
    <view class="nav " :class="{ 'nav--scrolled': scrolled }">
      <text class="back" @click="goBack()">←</text>
      <text class="nav-title">活动详情</text>
      <view class="nav-actions">
        <text class="act" @click="refresh()">⟳</text>
      </view>
    </view>

    <!-- 加载骨架 -->
    <view v-if="loading" class="skeleton">
      <view class="sk-cover shimmer"></view>
      <view class="card">
        <view class="sk-title shimmer"></view>
        <view class="sk-line shimmer" v-for="i in 4" :key="i"></view>
      </view>
      <view class="bottom">
        <view class="btn sk-btn shimmer"></view>
      </view>
    </view>

    <!-- 正常内容 -->
    <view v-else-if="detail" class="content">
      <!-- 顶部封面 + 渐变叠层 + 标题回落 -->
      <view class="hero">
        <image :src="detail.cover" class="cover" mode="aspectFill" />
        <view class="gradient"></view>
        <view class="hero-meta">
          <view class="badge" :class="statusClass">{{ statusText }}</view>
          <view class="hero-title">{{ detail.title }}</view>
        </view>
      </view>

      <!-- 信息卡片 -->
      <view class="card meta">
        <view class="row">
          <text class="k">⏰ 时间</text>
          <text class="v">{{ detail.startAt ? formatRange(detail.startAt, detail.endAt) : '时间待定' }}</text>
        </view>
        <view class="row" v-if="detail.location">
          <text class="k">📍 地点</text>
          <text class="v">{{ detail.location }}</text>
        </view>
        <view class="row" v-if="detail.campusClub?.name">
          <text class="k">🏷️ 社团</text>
          <text class="v">{{ detail.campusClub.name }}</text>
        </view>
        <view class="row">
          <text class="k">📌 状态</text>
          <text class="v"><text class="chip" :class="statusClass">{{ statusText }}</text></text>
        </view>

        <!-- 名额与热度 -->
        <view class="quota">
          <view class="quota-head">
            <text>👥 名额</text>
            <text>{{ detail.signedCount ?? 0 }}/{{ detail.quota ?? '-' }}</text>
          </view>
          <view class="bar">
            <view class="bar-fill" :style="{ width: progress + '%' }"></view>
            <view class="percent" :style="{ left: `calc(${progress}% - 14px)` }">{{ progress }}%</view>
          </view>
          <view class="quota-foot">
            <text>🔥 热度：{{ detail.heat ?? '-' }}</text>
            <text v-if="isFull" class="full">名额已满</text>
          </view>
        </view>
      </view>

      <!-- 活动介绍（可折叠） -->
      <!-- <view class="card desc">
        <view class="card-title">活动介绍</view>
        <view v-if="detail.desc" class="desc-text" :class="{ 'desc--collapsed': !descExpanded }">
          {{ detail.desc }}
        </view>
        <view v-else class="empty">暂无活动介绍</view>
        <view v-if="needExpand" class="expand" @click="descExpanded = !descExpanded">
          <text>{{ descExpanded ? '收起 ▲' : '展开更多 ▼' }}</text>
        </view>
      </view> -->

      <!-- 底部报名栏 -->
      <view class="bottom">
        <wd-button
          type="primary"
          size="large"
          :loading="signing"
          :disabled="!canSign"
          @click="onSignup"
        >
          <template v-if="signed">已报名</template>
          <template v-else-if="isFull">名额已满</template>
          <template v-else>立即报名</template>
        </wd-button>
      </view>
    </view>

    <!-- 空态（无数据或异常） -->
    <view v-else class="empty-page">
      <view class="empty-emoji">🪁</view>
      <view class="empty-text">活动不存在或已下线</view>
      <wd-button type="primary" size="large" @click="goBack">返回</wd-button>
    </view>
  </view>
</template>

<script lang="ts" setup>
import { ref, computed, onMounted } from 'vue'
import { onLoad, onPageScroll } from '@dcloudio/uni-app'
import { getActivityById, signupActivity, type Activity } from '@/mock/activity'
import { activitySignupPost, activitySignupGet } from '@/api/allApi'
const { safeAreaInsets } = uni.getSystemInfoSync()
const detail = ref<Activity | null>(null)
const signing = ref(false)
const signed = ref(false)
const loading = ref(true)
const scrolled = ref(false)

const descExpanded = ref(false)
const needExpand = ref(false)

let id = ''

onPageScroll((e) => {
  scrolled.value = e.scrollTop > 24
})

function formatRange(start: number, end?: number) {
  const f = (ts: number) => {
    const d = new Date(ts)
    const m = String(d.getMonth() + 1).padStart(2, '0')
    const day = String(d.getDate()).padStart(2, '0')
    const hh = String(d.getHours()).padStart(2, '0')
    const mm = String(d.getMinutes()).padStart(2, '0')
    return `${m}-${day} ${hh}:${mm}`
  }
  return end ? `${f(start)} ~ ${f(end)}` : `${f(start)}`
}

function getLoginUser() {
  return uni.getStorageSync('demo_user') || null
}

async function ensureLogin(): Promise<{ id: string; name: string } | null> {
  const u = getLoginUser()
  if (u) return u
  const res = await uni.showModal({
    title: '登录提示',
    content: '报名需要登录，是否一键登录（演示）？',
    confirmText: '一键登录'
  })
  if (res.confirm) {
    const demo = { id: 'demo-uid', name: '演示用户' }
    uni.setStorageSync('demo_user', demo)
    uni.showToast({ title: '已登录', icon: 'success' })
    return demo
  }
  return null
}

const isFull = computed(() => {
  if (!detail.value?.quota && detail.value?.quota !== 0) return false
  return (detail.value?.signedCount ?? 0) >= (detail.value?.quota ?? 0)
})
const canSign = computed(() => !signed.value && !isFull.value)

const progress = computed(() => {
  const total = detail.value?.quota ?? 0
  const used = detail.value?.signedCount ?? 0
  if (!total || total <= 0) return 0
  return Math.min(100, Math.round((used / total) * 100))
})

const statusText = computed(() => detail.value?.status || '未知')
const statusClass = computed(() => {
  const s = (detail.value?.status || '').toLowerCase()
  if (['进行中','报名中','open','ongoing','active'].includes(s)) return 'ok'
  if (['已结束','结束','closed','done','finished'].includes(s)) return 'end'
  if (['未开始','待开始','pending','upcoming'].includes(s)) return 'wait'
  return 'unk'
})

async function onSignup() {
  if (!detail.value || signing.value) return
  const user = await ensureLogin()
  if (!user) return
  signing.value = true
  try {
    const ok = await signupActivity(detail.value.id)
    if (ok) {
      signed.value = true
      detail.value.signedCount = (detail.value.signedCount ?? 0) + 1
      uni.showToast({ title: '报名成功', icon: 'success' })
    } else {
      uni.showToast({ title: '已报名过', icon: 'none' })
      signed.value = true
    }
  } finally {
    signing.value = false
  }
}

function refresh() {
  loading.value = true
  setTimeout(async () => {
    const data = await getActivityById(id)
    detail.value = data
    loading.value = false
  }, 250)
}

function goBack() {
  const pages = getCurrentPages()
  if (pages.length > 1) {
    uni.navigateBack()
  } else {
    uni.switchTab({ url: '/pages/activity/index' })
  }
}

onLoad((options) => {
  id = String(options.id || 0)
  // console.log("传入的id:", id)
})

onMounted(async () => {
  const data = await getActivityById(id)
  if (!data) {
    loading.value = false
    uni.showToast({ title: '活动不存在', icon: 'none' })
    setTimeout(() => goBack(), 800)
    return
  }
  detail.value = data
  const userInfoStr = localStorage.getItem('userInfo')
  const userInfo = JSON.parse(userInfoStr);

  activitySignupGet(id, userInfo['data']['id']).then((res) => {
    if (res['data']['items'].length >= 1) {
      signed.value = true
    }
  })

  // 文本是否需要折叠
  needExpand.value = !!(detail.value.desc && detail.value.desc.length > 120)
  loading.value = false
})
</script>

<style lang="scss">
$page-pad: 16px;
$radius: 14px;
$shadow: 0 8px 24px rgba(0,0,0,.08);

.page {
  background: #f5f6f8;
  padding-bottom: calc(env(safe-area-inset-bottom) + 88px);
  font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Microsoft YaHei", sans-serif;
}

.blur { backdrop-filter: blur(10px) saturate(1.2); }

.nav {
  height: 48px;
  display: grid;
  grid-template-columns: 48px 1fr 48px;
  align-items: center;
  padding: 0 $page-pad;
  position: sticky;
  top: 0;
  z-index: 20;
  background: rgba(255,255,255,0.78);
  transition: all .25s ease;
  &.nav--scrolled {
    background: rgba(255,255,255,0.96);
    box-shadow: 0 2px 10px rgba(0,0,0,.06);
  }
  .back { color: #2563eb; font-size: 20px; font-weight: 700; }
  .nav-title { text-align: center; font-weight: 700; font-size: 16px; color: #111827; }
  .nav-actions { text-align: right; .act { font-size: 16px; color: #6b7280; } }
}

.content { padding-bottom: 24px; }

.hero {
  position: relative;
  .cover {
    width: 100%;
    height: 240px;
    object-fit: cover;
    display: block;
  }
  .gradient {
    position: absolute; left: 0; right: 0; bottom: 0; height: 60%;
    background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(17,24,39,.75) 100%);
  }
  .hero-meta {
    position: absolute; left: $page-pad; right: $page-pad; bottom: 16px;
    color: #fff;
    display: grid; gap: 8px;
    .badge {
      display: inline-flex; align-items: center; gap: 6px;
      font-size: 12px; padding: 4px 8px; border-radius: 999px;
      &.ok { background: rgba(34,197,94,.9); }
      &.wait { background: rgba(59,130,246,.9); }
      &.end { background: rgba(244,63,94,.9); }
      &.unk { background: rgba(107,114,128,.9); }
    }
    .hero-title {
      font-size: 22px; font-weight: 800; line-height: 1.25;
      text-shadow: 0 2px 8px rgba(0,0,0,.35);
    }
  }
}

.card {
  background: #fff;
  margin: -20px $page-pad 16px;
  padding: 16px;
  border-radius: $radius;
  box-shadow: $shadow;
}

.meta {
  display: grid; gap: 10px;
  .row {
    display: grid; grid-template-columns: 72px 1fr; gap: 8px; align-items: baseline;
    .k { color: #6b7280; font-size: 13px; }
    .v { color: #111827; font-size: 15px; }
    .chip {
      padding: 2px 8px; border-radius: 999px; font-size: 12px; color: #fff;
      &.ok { background: #22c55e; }
      &.wait { background: #3b82f6; }
      &.end { background: #f43f5e; }
      &.unk { background: #9ca3af; }
    }
  }
  .quota {
    margin-top: 6px;
    .quota-head, .quota-foot { display: flex; justify-content: space-between; font-size: 13px; color: #6b7280; }
    .bar { height: 10px; background: #eef2f7; border-radius: 999px; overflow: hidden; margin: 8px 0;
      .bar-fill { height: 100%; background: linear-gradient(90deg, #60a5fa, #2563eb); width: 0; transition: width .35s ease; }
    }
    .full { color: #ef4444; }
  }
}

.desc {
  .card-title { font-weight: 700; font-size: 16px; margin-bottom: 8px; color: #111827; }
  .desc-text { color: #374151; font-size: 15px; line-height: 1.72; white-space: pre-wrap; }
  .desc--collapsed { max-height: 6.8em; overflow: hidden; position: relative; }
  .desc--collapsed::after {
    content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 48px;
    background: linear-gradient(180deg, rgba(255,255,255,0), #fff);
  }
  .expand { margin-top: 8px; color: #2563eb; font-size: 13px; }
  .empty { color: #9ca3af; font-size: 14px; }
}

.bottom {
  position: fixed; left: 0; right: 0; bottom: 0;
  padding: 10px $page-pad calc(env(safe-area-inset-bottom) + 10px);
  background: rgba(255,255,255,0.96);
  backdrop-filter: blur(10px) saturate(1.2);
  box-shadow: 0 -10px 24px rgba(0,0,0,.06);
  .btn { height: 44px; border-radius: 12px; }
}

/* 空态页 */
.empty-page {
  padding: 20vh $page-pad 0; text-align: center;
  .empty-emoji { font-size: 48px; }
  .empty-text { color: #6b7280; margin: 12px 0 16px; }
}

/* 骨架屏 */
.skeleton { padding-bottom: 88px; }
.sk-cover { width: 100%; height: 240px; background: #e5e7eb; }
.sk-title { height: 22px; border-radius: 6px; margin-bottom: 12px; background: #e5e7eb; }
.sk-line { height: 14px; border-radius: 6px; margin: 10px 0; background: #e5e7eb; }
.sk-btn { height: 44px; border-radius: 12px; background: #e5e7eb; }
.shimmer {
  position: relative; overflow: hidden;
  &::after {
    content: ''; position: absolute; inset: 0;
    background: linear-gradient(90deg, rgba(255,255,255,0), rgba(255,255,255,.6), rgba(255,255,255,0));
    transform: translateX(-100%);
    animation: shine 1.2s infinite;
  }
}
@keyframes shine { 100% { transform: translateX(100%); } }




/* 让卡片更自然地“顶上来”，并弱化封面下沿的黑带 */
.hero .gradient {
  height: 45%; /* 原先 60% -> 45%，减少压迫感 */
  mask-image: linear-gradient(180deg, #0000 0%, #000 90%, #000 100%); /* 柔和收边 */
}
.card { margin: 50px 16px 16px; border-radius: 16px; box-shadow: 0 10px 30px rgba(15, 23, 42, .08); }

/* 毛玻璃状态徽章，观感更透 */
.hero .hero-meta .badge {
  padding: 6px 10px;
  border-radius: 999px;
  backdrop-filter: saturate(1.4) blur(6px);
  border: 1px solid rgba(255,255,255,.35);
  background: linear-gradient(180deg, rgba(255,255,255,.18), rgba(255,255,255,.06));
  color: #fff;
}
.hero .hero-meta .badge.ok   { box-shadow: inset 0 0 0 999px rgba(34,197,94,.28); }
.hero .hero-meta .badge.wait { box-shadow: inset 0 0 0 999px rgba(59,130,246,.28); }
.hero .hero-meta .badge.end  { box-shadow: inset 0 0 0 999px rgba(244,63,94,.28); }
.hero .hero-meta .badge.unk  { box-shadow: inset 0 0 0 999px rgba(107,114,128,.28); }

/* 信息行间距与对比度微调，让卡片更松弛 */
.meta .row { gap: 10px; }
.meta .row .k { color: #7c8596; }

/* 进度条加百分比“气泡”与更细腻的渐变 */
.meta .quota .bar {
  position: relative;
  height: 12px;               /* 厚一点更显眼 */
  background: #eef2f7;
  border-radius: 999px;
  overflow: hidden;
  margin: 10px 0;
}
.meta .quota .bar .bar-fill {
  height: 100%;
  background: linear-gradient(90deg, #93c5fd, #3b82f6, #2563eb);
  transition: width .35s ease;
}
.meta .quota .bar .percent {
  position: absolute;
  top: -18px;
  font-size: 12px;
  line-height: 1;
  color: #2563eb;
}

/* 底部栏与主按钮更有层次感 */
.bottom {
  box-shadow: 0 -12px 28px rgba(15, 23, 42, .06);
}
:deep(.wd-button.is-primary) {
  height: 44px;
  border-radius: 12px;
  background: linear-gradient(90deg, #60a5fa, #2563eb) !important;
  box-shadow: 0 10px 20px rgba(37,99,235,.25);
}

/* 顶部导航滚动后更清晰 */
.nav.nav--scrolled {
  background: rgba(255,255,255,0.98);
  box-shadow: 0 2px 12px rgba(15,23,42,.08);
}

</style>
